package com.yinxing.webapi.code.controller;

import com.yinxing.framework.constant.SysConstant;
import com.yinxing.framework.domain.R;
import com.yinxing.framework.enums.RCode;
import com.yinxing.framework.system.SystemInfo;
import com.yinxing.framework.utils.IpUtils;
import com.yinxing.framework.utils.JwtUtils;
import com.yinxing.framework.utils.LongIdUtils;
import com.yinxing.netty.utils.ExtPushMessage;
import com.yinxing.netty.utils.ServerUtils;
import com.yinxing.webapi.code.service.sys.ISysUserService;
import com.yinxing.webapi.code.viewobje.sys.LoginVo;
import com.yinxing.webapi.code.viewobje.sys.RasswordResetVo;
import com.yinxing.webapi.config.AppConfig;
import com.yinxing.webapi.shiro.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.*;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/AppController")
public class AppController {

    @Autowired
    private AppConfig appConfig;

    @Autowired
    private ISysUserService sysUserService;

    /**
     * 系统登录
     * @param loginVo 登录信息实体类
     */
    @PostMapping("/login")
    public R login(@Validated LoginVo loginVo, HttpServletRequest request) {
        UsernamePasswordToken upToken = new UsernamePasswordToken();
        upToken.setUsername(loginVo.getUsername());
        upToken.setPassword(loginVo.getPassword().toCharArray());
        String userHost = IpUtils.getIpAddr(request);
        upToken.setHost(userHost);
        try {
            SecurityUtils.getSubject().login(upToken);
            Session session = SecurityUtils.getSubject().getSession();
            LoginUser loginUser = LoginUser.current();
            loginUser.setAuthToken(session.getId().toString());
            if ("on".equals(loginVo.getRememberMe())) {
                String jwtToken = JwtUtils.sign(loginUser.getUserId() + "", appConfig.getJwtSecure(), 15 * 24 * 60);
                loginUser.setJwtToken(jwtToken);
            }
            return R.ok(loginUser);
        } catch (ShiroException e) {
            return R.err(e.getMessage(), RCode.LOGIN_FAILURE);
        }
    }

    /**
     * 修改密码
     */
    @PostMapping("/passwordReset")
    public R passwordReset(@Validated RasswordResetVo resetVo) {
        if (!resetVo.getPasswordNew1().equals(resetVo.getPasswordNew2())) {
            return R.err("两次密码输入不一致");
        }
        sysUserService.passwordReset(LoginUser.current().getUserId(), resetVo.getPassword(), resetVo.getPasswordNew1());
        return R.ok("修改密码成功");
    }

    /**
     * 退出登录
     */
    @PostMapping("/logout")
    public R logout(HttpServletResponse response) {
        SecurityUtils.getSubject().logout();
        response.setHeader(SysConstant.JWT_TOKEN_HTTP_HEADER, SysConstant.EMPTY_STRING);
        return R.ok("退出登录成功");
    }

    /**
     * 心跳接口
     */
    @GetMapping("/heartbeat")
    public R heartbeat() {
        log.debug("heartbeat...");
        return R.ok();
    }

    /**
     * 获取用户信息
     */
    @GetMapping("/getUserInfo")
    public R getUserInfo() {
        LoginUser user = LoginUser.current();
        return R.ok(user);
    }

    /**
     * 获取全部在线用户
     */
    @GetMapping("/getOnlileUserList")
    public R getOnlileUserList(String QueryParam_) {
        List<LoginUser> userList = ServerUtils.getOnlileUserList();

        //条件查询
        if(StringUtils.hasLength(QueryParam_)) {
            userList = userList.stream().filter(loginUser ->
                    loginUser.getUsername().equals(QueryParam_)
                    || loginUser.getLoginName().equals(QueryParam_))
                .collect(Collectors.toList());
        }

        return R.ok(userList);
    }

    /**
     * 让用户下线
     * @param userId 用户ID
     */
    @PostMapping("/setUserOffline")
    public R setUserOffline (long userId) {
        ExtPushMessage message = new ExtPushMessage(ExtPushMessage.MessageType.OFF_LINE);
        ServerUtils.sendMessageToUser(userId, message);
        return R.ok();
    }

    /**
     * 获取系统信息
     */
    @GetMapping("/systemInfo")
    public R systemInfo() {
        return R.ok(SystemInfo.getSystemInfo());
    }

    /**
     * 获取Long类型ID
     */
    @GetMapping("/generatorLongId")
    public R generatorLongId() {
        long id = LongIdUtils.DEFAULT.nextId();
        return R.ok(id);
    }

    /**
     * 测试登录拦截
     */
    @RequiresAuthentication
    @GetMapping("/requiresAuthentication")
    public R requiresAuthentication() {
        return R.ok();
    }

    /**
     * 测试角色拦截
     */
    @RequiresRoles(value = {"admin", "system"}, logical = Logical.AND)
    @GetMapping("/requiresRoles")
    public R requiresRoles() {
        return R.ok();
    }

    /**
     * 测试权限拦截
     */
    @RequiresPermissions(value = {"update", "delete"}, logical = Logical.OR)
    @GetMapping("/requiresPermission")
    public R requiresPermission() {
        return R.ok();
    }

    /**
     * 记住我权限测试
     */
    @RequiresUser
    @GetMapping("/requiresUser")
    public R requiresUser() {
        return R.ok();
    }
}
